package com.cwz.quartz.controller;


import com.cwz.api.entity.SysJob;
import com.cwz.core.constant.Constants;
import com.cwz.core.result.R;
import com.cwz.core.utils.excel.ExcelUtils;
import com.cwz.core.utils.string.StringUtils;
import com.cwz.core.utils.task.TaskException;
import com.cwz.log.annotation.Log;
import com.cwz.log.enums.BusinessType;
import com.cwz.quartz.model.SysJobVo;
import com.cwz.quartz.service.SysJobService;
import com.cwz.quartz.utils.CronUtils;
import com.cwz.quartz.utils.ScheduleUtils;
import com.cwz.security.utils.SecurityUtils;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 定时任务调度表 前端控制器
 * </p>
 *
 * @author Wen
 * @since 2023-08-24
 */
@RestController
@RequestMapping("/job")
public class SysJobController {
	@Autowired
	private SysJobService sysJobService;

	/**
	 * 查询定时任务列表
	 */
	@GetMapping("/list")
	public R<Map<String, Object>> list(SysJobVo job) {
		return R.ok(this.sysJobService.selectJobList(job));
	}

	/**
	 * 获取定时任务详细信息
	 */
	@GetMapping(value = "/{jobId}")
	public R<SysJob> getInfo(@PathVariable("jobId") Long jobId) {
		return R.ok(this.sysJobService.selectJobById(jobId));
	}

	/**
	 * 新增定时任务
	 */
	@Log(title = "定时任务", businessType = BusinessType.INSERT)
	@PostMapping
	public R<Integer> add(@RequestBody SysJob job) throws TaskException, SchedulerException {
		if (!CronUtils.isValid(job.getCronExpression())) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，Cron表达式不正确");
		}
		else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'rmi'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS})) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'ldap(s)'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{Constants.HTTP, Constants.HTTPS})) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，目标字符串不允许'http(s)'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，目标字符串存在违规");
		}
		else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) {
			return R.fail("新增任务'" + job.getJobName() + "'失败，目标字符串不在白名单内");
		}
		job.setCreateBy(SecurityUtils.getUsername());
		return R.ok(this.sysJobService.insertJob(job));
	}

	/**
	 * 修改定时任务
	 */
	@Log(title = "定时任务", businessType = BusinessType.UPDATE)
	@PutMapping
	public R<Integer> edit(@RequestBody SysJob job) throws SchedulerException, TaskException {
		if (!CronUtils.isValid(job.getCronExpression())) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，Cron表达式不正确");
		}
		else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'rmi'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS})) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'ldap(s)'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[]{Constants.HTTP, Constants.HTTPS})) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，目标字符串不允许'http(s)'调用");
		}
		else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，目标字符串存在违规");
		}
		else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) {
			return R.fail("修改任务'" + job.getJobName() + "'失败，目标字符串不在白名单内");
		}
		job.setUpdateBy(SecurityUtils.getUsername());
		return R.ok(this.sysJobService.updateJob(job));
	}

	/**
	 * 定时任务状态修改
	 */
	@Log(title = "定时任务", businessType = BusinessType.UPDATE)
	@PutMapping("/changeStatus")
	public R<Integer> changeStatus(@RequestBody SysJob job) throws SchedulerException {
		return R.ok(this.sysJobService.changeStatus(job));
	}

	/**
	 * 定时任务立即执行一次
	 */
	@Log(title = "定时任务", businessType = BusinessType.UPDATE)
	@PutMapping("/run")
	public R<Void> run(@RequestBody SysJob job) throws SchedulerException {
		boolean result = this.sysJobService.run(job);
		return result ? R.ok("执行成功") : R.fail("任务不存在或已过期！");
	}

	/**
	 * 删除定时任务
	 */
	@Log(title = "定时任务", businessType = BusinessType.DELETE)
	@DeleteMapping("/{jobIds}")
	public R<Void> remove(@PathVariable Long[] jobIds) throws SchedulerException {
		this.sysJobService.deleteJobByIds(jobIds);
		return R.ok("删除成功");
	}

	/**
	 * 导出定时任务列表
	 */
	@Log(title = "定时任务", businessType = BusinessType.EXPORT)
	@PostMapping("/export")
	public void export(HttpServletResponse response, SysJobVo sysJob) {
		List<SysJob> list = (List<SysJob>) this.sysJobService.selectJobList(sysJob).get("list");
		ExcelUtils<SysJob> utils = new ExcelUtils<>(SysJob.class);
		utils.exportExcel(response, list, "定时任务");
	}

	// 数组接收数据
	@PostMapping("/test1")
	public String test(@RequestBody List<String> strings) {
		return String.join(",", strings);
	}

	// map接收数据
	@PostMapping("/test2")
	public String test(@RequestBody Map<String, Object> map) {
		return String.join(",", (List<String>) map.get("strings"));
	}
}

